
#include "Engine/common.h"
#include "DNF定义.h"
#include "DNF对象定义.h"

//https://baijiahao.baidu.com/s?id=1796001615197904853&wfr=spider&for=pc
float 防具精通_品质常数[品质总数]={-1,2,5,8,11,14,17};
float 防具精通_部位比例[5]={0.3, 0.25, 0.2, 0.1, 0.15};

void DNF职业对象::重置属性()
{
	for (int i=0;i<技能总数量;i++)
	{
		技能等级增加量[i]=0;
		技能攻击力增加量[i]=1.0f;
		技能冷却剩余量[i]=1.0f;
		技能恢复加快量[i]=0;
		技能无色数量[i]=职业技能列表[i]->无色数量;
		技能无色攻击力增加量[i]=1.0f;
		技能手搓伤害倍率[i]=1.0f;
		技能手搓冷却倍率[i]=1.0f;
	}
	技能冷却削减量=0.0f;
	全部TP技能等级增加量=0;
	技能冷却减少记录=1.0f;
	技能恢复加快记录=0.0f;
}

void DNF职业对象::技能等级增加(WCHAR* 技能名,int 等级数)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (wstreql(职业技能列表[i]->名称,技能名))
		{
			技能等级增加量[i]+=等级数;
			return ;
		}
	}
}

void DNF职业对象::技能等级增加(int 起始等级,int 结束等级,int 等级数,int 技能类型过滤)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->学习等级>=起始等级 && 职业技能列表[i]->学习等级<=结束等级 && 
			((职业技能列表[i]->技能类型&技能类型过滤)!=0))
		{
			//主动技能的计算以次数为准，0级仍会受到加成，被动技能0级时视为关闭，不接受加成
			if (职业技能列表[i]->技能类型==被动技能 && 当前角色对象->技能等级[i]==0)
				continue;
			技能等级增加量[i]+=等级数;
			//最高加至上限
			if (当前角色对象->技能等级[i]+技能等级增加量[i]>职业技能列表[i]->等级上限)
				技能等级增加量[i]=职业技能列表[i]->等级上限-当前角色对象->技能等级[i];
			//最低减至0
			if (当前角色对象->技能等级[i]+技能等级增加量[i]<0)
				技能等级增加量[i]=-当前角色对象->技能等级[i];
		}			
	}
}

void DNF职业对象::技能攻击力增加(int 起始等级,int 结束等级,float 增加量,int 技能类型过滤)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->学习等级>=起始等级 && 职业技能列表[i]->学习等级<=结束等级 && 
			((职业技能列表[i]->技能类型&技能类型过滤)!=0))
			技能攻击力增加量[i]*=1.0f+增加量;	//乘算
	}
}

void DNF职业对象::技能冷却减少(int 起始等级,int 结束等级,float 减少量,int 技能类型过滤)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->学习等级>=起始等级 && 职业技能列表[i]->学习等级<=结束等级 && 
			((职业技能列表[i]->技能类型&技能类型过滤)!=0))
			技能冷却剩余量[i]*=1.0f-减少量;	//乘算
	}
	//全等级范围的调用（来源是被动的除外），都在面板上显示（110绝大多数减冷却效果都不包含觉醒技）
	if (起始等级==1 && 结束等级==100 && (技能类型过滤&主动非觉醒技能)==主动非觉醒技能 && 当前角色对象->面板冷却统计开关)
		技能冷却减少记录*=1.0f-减少量;
}

void DNF职业对象::技能恢复加快(int 起始等级,int 结束等级,float 加快量,int 技能类型过滤)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->学习等级>=起始等级 && 职业技能列表[i]->学习等级<=结束等级 && 
			((职业技能列表[i]->技能类型&技能类型过滤)!=0))
			技能恢复加快量[i]+=加快量;	//加算
	}
	//全等级范围的调用（来源是被动的除外），都在面板上显示（110绝大多数减冷却效果都不包含觉醒技）
	if (起始等级==1 && 结束等级==100 && (技能类型过滤&主动非觉醒技能)==主动非觉醒技能 && 当前角色对象->面板冷却统计开关)
		技能恢复加快记录+=加快量;
}

void DNF职业对象::技能冷却削减(float 技能冷却削减量)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	this->技能冷却削减量+=技能冷却削减量;
}

void DNF职业对象::技能无色攻击力增加(int 起始等级,int 结束等级,float 增加量,int 最低无色,int 最高无色)
{
	//几件涉及无色的装备，先计算无色数量，后续才能计算各种无色词条：
	//1.恐惧缠绕腰带：不消耗无色的技能，无色+2，会把非无色技能变成无色技能，影响后续计算
	//2.堕落的灵魂：消耗无色的技能，无色+2
	//3.自由之缚手镯：无色消耗量变8倍，先加后乘，上限16（会把超过16个的变成16）

	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->学习等级>=起始等级 && 职业技能列表[i]->学习等级<=结束等级 &&
			((职业技能列表[i]->技能类型&主动全部技能)!=0))
		{
			if (技能无色数量[i]>=最低无色 && 技能无色数量[i]<=最高无色)
				技能无色攻击力增加量[i]*=1.0f+增加量;	//乘算
		}
	}
}

void DNF职业对象::技能无色冷却减少(float 减少量,int 最低无色,int 最高无色)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if ((职业技能列表[i]->技能类型&主动非觉醒技能)!=0)
		{
			if (技能无色数量[i]>=最低无色 && 技能无色数量[i]<=最高无色)
				技能冷却剩余量[i]*=1.0f-减少量;	//乘算
		}
	}
	if (当前角色对象->面板冷却统计开关)
		技能冷却减少记录*=1.0f-减少量;
}

void DNF职业对象::技能手搓伤害倍率提升(float 提升率,int 技能类型过滤)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	for (int i=0;i<技能总数量;i++)
	{
		if ((职业技能列表[i]->技能类型&技能类型过滤)!=0)
			技能手搓伤害倍率[i]*=1.0f+提升率;	//都是乘算技攻
	}
}

void DNF职业对象::技能手搓冷却倍率增加(float 提升量,BOOL 无色技能)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	//现在观察只有这几件有此词条：高科技战术强化靴，恩特护肩，红皮武器
	//条件均为觉醒技能除外，但是会区分是否无色技能，需要先统计无色数
	for (int i=0;i<技能总数量;i++)
	{
		if ((职业技能列表[i]->技能类型&主动非觉醒技能)!=0)
		{
			if (无色技能)
			{
				if (技能无色数量[i]!=0)
					技能手搓冷却倍率[i]+=提升量;
			}
			else
				技能手搓冷却倍率[i]+=提升量;	//加算
		}
	}
}

void DNF职业对象::全部TP技能等级增加(int 等级数)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改伤害类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	全部TP技能等级增加量+=等级数;
}

void DNF职业对象::设置技能无色数(int 技能索引,int 无色数)
{
	if (当前角色对象->属性控制状态!=DNF角色对象::属性控制_仅修改条件类 &&
		当前角色对象->属性控制状态!=DNF角色对象::属性控制_各类属性都可修改)
		return ;
	技能无色数量[技能索引]=无色数;
}

//////////////////////////////////////////////////////////////////////////

int DNF职业对象::计算技能等级(int 技能索引)
{
	return 当前角色对象->技能等级[技能索引]+技能等级增加量[技能索引];
}

double DNF职业对象::计算技能单次基础伤害(int 技能索引)
{
	int 技能等级=计算技能等级(技能索引);
	int 技能TP等级=min(当前角色对象->技能TP等级[技能索引]+全部TP技能等级增加量,职业技能列表[技能索引]->TP等级上限);
	double 技能伤害=职业技能列表[技能索引]->获取伤害(技能等级,技能TP等级,当前角色对象->技能使用护石[技能索引]);

	//符文属性互相乘算
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].红色数量;i++)
		技能伤害*=1.06f;
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].紫色数量;i++)
		技能伤害*=1.04f;
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].绿色数量;i++)
		技能伤害*=0.96f;

	技能伤害*=技能攻击力增加量[技能索引];
	技能伤害*=技能无色攻击力增加量[技能索引];	//需要先统计无色数量
	return 技能伤害;
}

float DNF职业对象::计算技能单次基础冷却(int 技能索引)
{
	//冷却计算参考了这里
	//https://bbs.colg.cn/thread-8508174-1-1.html

	float 技能冷却=职业技能列表[技能索引]->获取冷却(当前角色对象->技能使用护石[技能索引]);
	技能冷却*=1.0f-技能冷却削减量;

	//符文属性互相乘算
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].红色数量;i++)
		技能冷却*=1.04f;
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].蓝色数量;i++)
		技能冷却*=0.95f;
	for (int i=0;i<当前角色对象->技能符文数量[技能索引].绿色数量;i++)
		技能冷却*=0.93f;
	技能冷却*=技能冷却剩余量[技能索引];
	技能冷却/=1.0f+技能恢复加快量[技能索引];

	return 技能冷却;
}

void DNF职业对象::应用被动技能(int 技能索引)
{
	int 技能等级=计算技能等级(技能索引);
	if (技能等级!=0)	//被动没有技能次数，以技能等级判断是否应用
		职业技能列表[技能索引]->应用被动技能(技能等级);
}

double DNF职业对象::计算技能总伤害(int 技能索引)
{
	//单次伤害忽略与次数有关的设置
	//UI不展示单次伤害，而是总伤害和平均伤害，会把次数加入计算
	double 技能伤害=计算技能单次基础伤害(技能索引);
	//子类需要实现技能的条件增伤，以及Buff增伤
	技能伤害=职业技能伤害调整(技能索引,技能伤害);

	//高科技闪影项链特别处理
	float 手搓额外倍率=1.0f;
	if (当前角色对象->部位穿戴装备检查(项链,L"高科技闪影项链") && 当前角色对象->技能在快捷栏里[技能索引])
		手搓额外倍率=1.1f;

	//转换函数保证宠物和手搓次数不超过技能次数，如果相等则为100%占比
	int 技能次数=当前角色对象->技能次数[技能索引];
	float 宠物平均提升=当前角色对象->技能受宠物加成次数[技能索引]/(float)技能次数*PC(10)+1.0f;
	float 手搓平均提升=当前角色对象->技能受手搓加成次数[技能索引]/(float)技能次数*(技能手搓伤害倍率[技能索引]*手搓额外倍率-1.0f)+1.0f;
	技能伤害*=技能次数*宠物平均提升*手搓平均提升;
	//这里忽略了一种可能，职业的每次技能都会因条件不同而伤害变化，比如第一次100%伤害，第二次120%伤害
	//如果真的存在这种职业，子类还需要实现一个总伤害调整的接口，把[宠物平均提升]和[手搓平均提升]当做参数传入
	return 技能伤害;
}

double DNF职业对象::计算技能最终冷却(int 技能索引)
{
	//UI只展示单次冷却，不考虑平均冷却，因为平均冷却可能给人误导
	//对于与次数有关的减冷却效果，仅在子类的 职业技能冷却调整() 进行说明，不进行实际计算
	//对于手搓冷却，不考虑手搓次数的影响，搓了就显示最低冷却
	float 技能冷却=计算技能单次基础冷却(技能索引);
	//子类需要实现技能的条件减冷却
	技能冷却=职业技能冷却调整(技能索引,技能冷却);
	if (当前角色对象->技能受手搓加成次数[技能索引]!=0)
	{
		float 手搓冷却剩余量=1.0f-职业技能列表[技能索引]->手搓冷却缩减*技能手搓冷却倍率[技能索引];
		技能冷却*=手搓冷却剩余量;
	}

	//高科技闪影项链特别处理(只要搓了就显示最低冷却)
	if (当前角色对象->部位穿戴装备检查(项链,L"高科技闪影项链") && 当前角色对象->技能在快捷栏里[技能索引]==FALSE &&
		职业技能列表[技能索引]->技能类型!=觉醒技能)
		技能冷却*=0.85f;

	//无论怎么减，都不能突破70%上限
	float 技能冷却上限=职业技能列表[技能索引]->冷却时间*0.3f;
	if (技能冷却<技能冷却上限)
		技能冷却=技能冷却上限;
	return 技能冷却;
}

int DNF职业对象::获取白金徽章技能列表(WCHAR** 结果缓冲区)
{
	int n=0;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->白金徽章可选)
		{
			结果缓冲区[n]=职业技能列表[i]->名称;
			n++;
		}
	}
	return n;
}

int DNF职业对象::获取装扮上衣技能列表(WCHAR** 结果缓冲区)
{
	int n=0;
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->时装上衣可选)
		{
			结果缓冲区[n]=职业技能列表[i]->名称;
			n++;
		}
	}
	return n;
}

int DNF职业对象::获取技能索引(WCHAR* 技能名)
{
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->名称!=NULL && wcscmp(职业技能列表[i]->名称,技能名)==0)
			return i;
	}
	return -1;
}

BOOL DNF职业对象::施放了觉醒技能()
{
	for (int i=0;i<技能总数量;i++)
	{
		if (职业技能列表[i]->技能类型==觉醒技能)
		{		
			if (当前角色对象->技能次数[i]!=0)
				return TRUE;
		}
	}
	return FALSE;
}